use crate::core::vec3::*;
use crate::core::ray::*;

use super::rtweekend::degrees_to_radians;

pub struct Camera{
    origin: Point3,
    lower_left_corner: Point3,
    horizontal: Vec3New,
    vertical: Vec3New,
    u: Vec3New,
    v: Vec3New,
    w: Vec3New,
    lens_radius: f64,
}

impl Camera{
    pub fn new(lookfrom:Point3, lookat:Point3, vup:Vec3New, vfov:f64, aspect_ratio:f64, aperture:f64, focus_dist:f64) -> Self{
        let theta = degrees_to_radians(vfov);
        let h = (theta/2.0).tan();
        // let aspect_ratio = 16_f64 / 9_f64;
        let viewport_height = 2_f64 * h;
        let viewport_width = aspect_ratio * viewport_height;

        // let focal_length = 1_f64;

        // let origin = Point3::new();
        // let horizontal = Vec3New::from(viewport_width, 0_f64, 0_f64);
        // let vertical = Vec3New::from(0_f64, viewport_height, 0_f64);
        // let lower_left_corner = origin - &(&horizontal/2_f64) - &(&vertical/2_f64) - &Vec3New::from(0_f64, 0_f64, focal_length);
        
        
        let w: Vec3New = unit_vector(&(lookfrom - lookat));
        let u = unit_vector(&cross(&vup, &w));
        let v = cross(&w, &u);

        let origin = lookfrom;
        let horizontal = focus_dist * viewport_width * &u;
        let vertical = focus_dist * viewport_height * &v;
        let lower_left_corner = origin - (&horizontal/2.0) - (&vertical/2.0) - focus_dist*&w;

        let lens_radius = aperture / 2.0;
        Self{
            origin,
            lower_left_corner,
            horizontal,
            vertical,
            u,
            v,
            w,
            lens_radius,
        }
    }

    pub fn get_ray(&self, s:f64, t:f64) -> Ray{
        let rd = self.lens_radius * &random_in_unit_disk();
        let offset = &self.u * rd.get_x() + &self.v * rd.get_y();

        Ray{
            orig: &self.origin + &offset,
            dir: &self.lower_left_corner + &(s*&self.horizontal) + t*&self.vertical - &self.origin - &offset,
        }

        // Ray::from(&self.origin, &(&self.lower_left_corner + &(s*&self.horizontal) + &(t*&self.vertical) - &self.origin))
        // ray(origin, lower_left_corner + u*horizontal + v*vertical - origin)
    }
}

// 也可使用标准库中函数x.clamp(min, max)
pub fn clamp(x: f64, min: f64, max: f64) -> f64{
    // x.clamp(min, max)
    match x {
        x if x < min => min,
        x if x > max => max,
        _ => x
    }
}